package logger

import (
	"github.com/sirupsen/logrus"
	"gopkg.in/natefinch/lumberjack.v2"
	"io/ioutil"
)

// 日志配置
type LoggerConf struct {
	LogFileMaxSize    int    `json:"log_file_max_size"`    // 单位: MB
	LogFileMaxBackups int    `json:"log_file_max_backups"` // 日志保存份数
	LogFileMaxAge     int    `json:"log_file_max_age"`     // 保留过期文件的最大时间间隔,单位是天
	LogFileCompress   bool   `json:"log_file_compress"`    // 是否需要压缩滚动日志, 使用的 gzip 压缩
	FlagLogLevel      string `json:"flag_log_level"`       // 日志打印级别
	FlagLogFile       string `json:"flag_log_file"`        // 日志保存位置
	FlagLogNoStdout   bool   `json:"flag_log_no_stdout"`   // 不在控制台输出
}

// 测试配置
var loggerConf = LoggerConf{
	LogFileMaxSize:    300,
	LogFileMaxBackups: 1,
	LogFileMaxAge:     28,
	LogFileCompress:   true,
	FlagLogLevel:      "info",
	FlagLogFile:       "log/log_test.log",
	FlagLogNoStdout:   false,
}

var (
	logFileMaxSize    = loggerConf.LogFileMaxSize    // 单位: MB
	logFileMaxBackups = loggerConf.LogFileMaxBackups // 日志保存份数
	logFileMaxAge     = loggerConf.LogFileMaxAge     // 保留过期文件的最大时间间隔,单位是天
	logFileCompress   = loggerConf.LogFileCompress   // 是否需要压缩滚动日志, 使用的 gzip 压缩
	flagLogLevel      = loggerConf.FlagLogLevel      // 日志打印级别
	flagLogFile       = loggerConf.FlagLogFile       // 日志保存位置
	flagLogNoStdout   = loggerConf.FlagLogNoStdout   // 不在控制台输出

	log = GetLogger("logger-config")
)

// 日志初始化配置信息
func init() {

	// 设置日志级别
	fn, ok := logLevels[flagLogLevel]
	if !ok {
		log.Fatalf("Invalid log level '%s'. Valid log levels are %v", flagLogLevel, getLogLevels())
	}
	fn(log.Logger)
	log.Infof("Setting log level to '%s'", flagLogLevel)

	// 设置日志保存文件
	if flagLogFile != "" {
		log.Infof("Logging to file %s", flagLogFile)
		logger := &lumberjack.Logger{
			// 日志输出文件路径
			Filename: flagLogFile,
			// 日志文件最大 size, 单位是 MB
			MaxSize: logFileMaxSize, // megabytes
			// 最大过期日志保留的个数
			MaxBackups: logFileMaxBackups,
			// 保留过期文件的最大时间间隔,单位是天
			MaxAge: logFileMaxAge, //days
			// 是否需要压缩滚动日志, 使用的 gzip 压缩
			Compress: logFileCompress, // disabled by default
		}
		// 指定文件(此处用了第三方管理的文件流, 以实现对文件的大小控制和切分)
		WithFile(log, logger)
	}

	// 设置日志是否控制台输出
	if flagLogNoStdout {
		log.Infof("Disabling logging to stdout/stderr")
		WithNoStdOutErr(log)
	}
	return
}

var logLevels = map[string]func(*logrus.Logger){
	"none":    func(l *logrus.Logger) { l.SetOutput(ioutil.Discard) },
	"debug":   func(l *logrus.Logger) { l.SetLevel(logrus.DebugLevel) },
	"info":    func(l *logrus.Logger) { l.SetLevel(logrus.InfoLevel) },
	"warning": func(l *logrus.Logger) { l.SetLevel(logrus.WarnLevel) },
	"error":   func(l *logrus.Logger) { l.SetLevel(logrus.ErrorLevel) },
	"fatal":   func(l *logrus.Logger) { l.SetLevel(logrus.FatalLevel) },
}

func getLogLevels() []string {
	var levels []string
	for k := range logLevels {
		levels = append(levels, k)
	}
	return levels
}
